#!/bin/bash

######################################################################
# Generate helper code for making builtin DSO plugins available.
#
# Sometimes it is necessary to split a plugin to several source
# files. Usually this is the case when the functionality provided
# by the plugin is complex enough to require subdividing the plugin
# into internal modules for the best maintainability.
#
# In these cases we cannot avoid making several functions and
# variables globally available within the plugin so we cannot just
# limit the scope of visibility by making them static. Still, we do
# want to avoid conflicts between these symbols of different plugins.
# To accomplish this we compile and link such plugins into shared
# libraries (with our normal symbol visibility conventions) and then
# link the murphy daemon against them.
#
# Since none of the code linked into murphy proper references
# any of the symbols in any of these plugins without any further
# special arrangements these plugins wouldn't be demand-loaded
# and consequently would be unavailable when the daemon starts up.
#
# To overcome this every such plugin gets automatically augmented
# by a plugin-specifig globally visible symbol and the murphy daemon
# gets augmented by a symbol that references these plugin-specific
# symbols. This forces the dynamic loader to load the plugins and
# the normal builtin-plugin autoregistration mechanism takes care of
# the rest.
#
# A bit too spaceship-ish, I admit... but nevertheless necessary
# unless we want to give up the idea of builtin/linkedin plugins...
#


error () {
    echo "error: $*" 1>&2
}

info () {
    echo "$*" 1>&2
}

warning () {
    echo "warning: $*" 1>&2
}

usage () {
    info "usage: $0 -p <plugin> -o <output-file>, or"
    info "usage: $0 -o <output-file> -d <plugin-list>"
    exit ${1:-1}
}

emit () {
    echo "$*" >> $OUTPUT
}

emit_plugin_loader () {
    case $OUTPUT in
        *.c) emit "int mrp_linkedin_plugin_${1//-/_}_symbol = 0;"
             ;;
        *.h) emit "extern int mrp_linkedin_plugin_${1//-/_}_symbol;"
             ;;
    esac
}

emit_murphy_loader () {
    local _p

    for _p in $*; do
        emit "#include \"linkedin-$_p-loader.h\""
    done
    emit ""
    emit "int mrp_load_linkedin_plugins(void)"
    emit "{"
    emit "    return \\"
    for _p in $*; do
        emit "        mrp_linkedin_plugin_${_p//-/_}_symbol + \\"
    done
    emit "        0;"
    emit "}"
}


OUTPUT=""
PLUGIN=""
PLUGIN_LIST=""
daemon=no

#echo "*** $0 $* ***"

# parse command line
while [ -n "${1#-}" ]; do
    case $1 in
        -o)
            if [ -z "$OUTPUT" ]; then
                shift
                OUTPUT="$1"
            else
                error "Multiple output files requested."
                usage
            fi
            ;;
        -p)
            if [ -z "$PLUGIN" -a "$daemon" = "no" ]; then
                shift
                PLUGIN="$1"
            else
                if [ -n "$PLUGIN" ]; then
                    error "Multiple builtin plugins specified."
                else
                    error "Both builtin plugin and plugin list specified."
                fi
                usage
            fi
            ;;

        -h)
            usage 0
            ;;
	-q)
	    QUIET="yes"
	    ;;
        -d)
            daemon=yes
            ;;

        -*)
            error "Unknown option '$1'."
            usage
            ;;

        *)
            if [ "$daemon" = "yes" ]; then
                PLUGIN_LIST="$PLUGIN_LIST $1"
            else
                error "Unexpected argument '$1'."
                usage
            fi
            ;;
    esac
    shift
done

# check that we've got everything mandatory
if [ -z "$OUTPUT" ]; then
    error "No output file specified (use the -o option)."
    usage
fi

if [ -z "$PLUGIN" -a "$daemon" = "no" ]; then
    error "Neither builtin plugin nor plugin list is specified."
    usage
fi

# generate the output
rm -f $OUTPUT
touch $OUTPUT
if [ "$daemon" = "no" ]; then
    emit_plugin_loader $PLUGIN
else
    emit_murphy_loader $PLUGIN_LIST
fi
